#!/usr/bin/env python
# -*- coding: utf-8 -*-
# http://docs.python.org/whatsnew/pep-328.html
from __future__ import absolute_import
from __future__ import print_function   # deletes the print statement
# from __future__ import unicode_literals # unicode by default

from cherrypy import request, response
from genshi.template import TemplateLoader
from genshi import Markup
from webpyte import dir_wp, ShowUserThisException


def email_to_friend(text='Send to a friend', email='Visit:',
                    css='EmailFriend', title='Email this page to a friend'):
    """Creates a mailto: link so a friend can visit the current page."""
    domain = request.headers["host"]
    page = "http://" + domain + request.path_info
    s = '''<a class="%s" title='%s' href="mailto:?Subject=Site%%20%s''' \
        '''&amp;Body=%s%%20%s">%s</a>''' % (css, title, domain, email, page, text)
    return Markup(s)



class Gensher(object):
    """Genshi integration for Webpyte."""
    def __init__(self, app):
        self.app = app
        # Several javascript files (and more) are served from
        # /wp - a static section:
        app.merge({"/wp":{
            "tools.staticdir.on": True,
            "tools.staticdir.root": None,
            "tools.staticdir.dir": dir_wp + "/static",
        }})
        # Each app has its own Genshi TemplateLoader
        self._loader = \
            TemplateLoader([dir_wp + "/templates"], auto_reload=True)
        # The following instance variables can be easily changed by the app
        self.method = "xhtml"
        self.doctype = "xhtml-transitional"
        self.errortemplate = "error.html"
    
    def add_search_path(self, path):
        """Adds a directory to the template loader search path.
        You can specify templates by base name as long as the directories
        in which they reside are in the search path.
        """
        if path not in self._loader.search_path:
            self._loader.search_path.append(path)
    
    def fragment(self, template_file, dic, method=None):
        """Loads a Genshi template and returns its output as
        an XHTML fragment, taking care of some details.
    
        - template_file is the name of the Genshi template file to be rendered.
        - dic is a dictionary to populate the template instance.
        """
        t = self._loader.load(template_file)
        # encoding=None will return a unicode object:
        return t.generate(**self.app.totemplate(**dic)) \
            .render(method=method or self.method, encoding=None)
    
    def page(self, template_file, dic):
        """Loads a Genshi template and returns its output as
        an XHTML page, taking care of some details.
        
        - template_file is a path, relative to the app directory.
        - dic is a dictionary to populate the template instance.
        """
        if isinstance(dic, basestring):
            return dic
        t = self._loader.load(template_file)
        return t.generate(**self.app.totemplate(**dic)) \
            .render(method=self.method, encoding="utf-8", doctype=self.doctype)
    
    def error(self, msg, status='500'):
        """Clears the SQLAlchemy session, sets the HTTP response code to 500
        and displays a customizable error message to the user.
        """
        response.headers["Status"] = str(status)
        # FIRST assemble the error page,
        if isinstance(msg, Exception):  msg = msg[0] #unicode(msg) #(msg.message)
        page = self.page(self.errortemplate, self.app.totemplate(msg=msg))
        # and only rollback after that:
        if hasattr(self.app, "sa"): # TODO: This code is obsolete. Delete or replace?
            self.app.sa.rollback()
        return page



def page(template=None):
    """Decorator for easily rendering a Genshi template as a page. Example:
    
    @page("hello.html")
    def hello(self):
        return dict(message="Nobody expects the Spanish Inquisition!!!")
    
    If your code (usually the model) throws a
    webpyte.ShowUserThisException, this decorator catches it and
    shows it through the Gensher.error() method.
    """
    def decorate(func):
        def wrap(*a, **kw):
            request.exception = None # A place to store exceptions
            try:
                result = func(*a, **kw)
            except ShowUserThisException as e: # Since we are consuming this
                request.exception = e          # exception, we store it so
                return request.app.gensher.error(e) # others can know about it.
            return result if template is None \
                else request.app.gensher.page(template, result)
        wrap.__doc__ = func.__doc__
        return wrap
    return decorate

def fragment(template=None):
    """Decorator for easily rendering an HTML fragment from a Genshi template.
    Example:
    
    @fragment("templates/header.html")
    def header(self):
        return dict(message="Nobody expects the Spanish Inquisition!!!")
    """
    def decorate(func):
        def wrap(*a, **kw):
            result = func(*a, **kw)
            return result if template is None \
                else request.app.gensher.fragment(template, result)
        wrap.__doc__ = func.__doc__
        return wrap
    return decorate


class gensher(object):
    """A proxy to make it easy to use Gensher methods such as
    error(), fragment(), page() etc. without writing "request.app.gensher"
    every time.
    """
    def __getattr__(self, attrib):
        return getattr(request.app.gensher, attrib)
gensher = gensher()
